{{!

  Copyright (c) Meta Platforms, Inc. and affiliates.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

}}{{!
Metadata for Thrift types
}}
{{> common/auto_generated_py}}

import apache.thrift.metadata.thrift_types as _fbthrift_metadata

import {{program:module_path}}.thrift_enums as _fbthrift_current_module_enums
import {{program:module_path}}.thrift_enums

{{#program:include_namespaces}}
{{#has_types?}}

import {{included_module_path}}.thrift_enums
{{/has_types?}}
import {{included_module_path}}.thrift_metadata as {{included_module_mangle}}__thrift_metadata
{{/program:include_namespaces}}

{{#program:structs}}
# TODO (ffrancet): This general pattern can be optimized by using tuples and dicts
# instead of re-generating thrift structs
def _fbthrift_gen_metadata_{{#struct:exception?}}exception{{/struct:exception?}}{{^struct:exception?}}struct{{/struct:exception?}}_{{> structs/unadapted_name}}({{!
}}metadata_struct: _fbthrift_metadata.ThriftMetadata) -> _fbthrift_metadata.ThriftMetadata:
    qualified_name = "{{program:name}}.{{> structs/unadapted_name}}"

    if qualified_name in metadata_struct.{{#struct:exception?}}exceptions{{/struct:exception?}}{{^struct:exception?}}structs{{/struct:exception?}}:
        return metadata_struct
    fields = [
        {{#struct:fields_ordered_by_id}}
        _fbthrift_metadata.ThriftField(id={{field:id}}, type={{#field:type}}{{> metadata/thrift_type }}{{/field:type}}, name="{{field:name}}", is_optional={{#field:optional?}}True{{/field:optional?}}{{^field:optional?}}False{{/field:optional?}}, structured_annotations=[
            {{#field:structured_annotations}}
            {{#structured_annotation:const_struct?}}{{#structured_annotation:const}}{{#constant:value}}
            {{> metadata/const_struct }},
            {{/constant:value}}{{/structured_annotation:const}}{{/structured_annotation:const_struct?}}
            {{/field:structured_annotations}}
        ]),
        {{/struct:fields_ordered_by_id}}
    ]
    struct_dict = dict(metadata_struct.{{#struct:exception?}}exceptions{{/struct:exception?}}{{^struct:exception?}}structs{{/struct:exception?}})
    struct_dict[qualified_name] = _fbthrift_metadata.{{!
    }}{{#struct:exception?}}ThriftException{{/struct:exception?}}{{^struct:exception?}}ThriftStruct{{/struct:exception?}}(name=qualified_name, fields=fields,
    {{^struct:exception?}}
        is_union={{#struct:union?}}True{{/struct:union?}}{{^struct:union?}}False{{/struct:union?}},
    {{/struct:exception?}}
        structured_annotations=[
            {{#struct:structured_annotations}}
            {{#structured_annotation:const_struct?}}{{#structured_annotation:const}}{{#constant:value}}
            {{> metadata/const_struct }},
            {{/constant:value}}{{/structured_annotation:const}}{{/structured_annotation:const_struct?}}
            {{/struct:structured_annotations}}
        ])
    new_struct = metadata_struct({{#struct:exception?}}exceptions{{/struct:exception?}}{{^struct:exception?}}structs{{/struct:exception?}}=struct_dict)

    {{#struct:fields}}
    {{#field:type}}
    # {{field:name}}
    {{> metadata/recursive_call }}
    {{/field:type}}
    {{/struct:fields}}

    return new_struct
def gen_metadata_{{#struct:exception?}}exception{{/struct:exception?}}{{^struct:exception?}}struct{{/struct:exception?}}_{{> structs/unadapted_name}}() -> _fbthrift_metadata.ThriftMetadata:
    return _fbthrift_gen_metadata_{{#struct:exception?}}exception{{/struct:exception?}}{{^struct:exception?}}struct{{/struct:exception?}}_{{> structs/unadapted_name}}({{!
    }}_fbthrift_metadata.ThriftMetadata(structs={}, enums={}, exceptions={}, services={}))

{{/program:structs}}

{{#program:services}}
def gen_metadata_service_{{service:name}}() -> _fbthrift_metadata.ThriftMetadata:
    return _fbthrift_gen_metadata_service_{{service:name}}(_fbthrift_metadata.ThriftMetadata(structs={}, enums={}, exceptions={}, services={}))

def _fbthrift_gen_metadata_service_{{service:name}}({{!
}}metadata_struct: _fbthrift_metadata.ThriftMetadata) -> _fbthrift_metadata.ThriftMetadata:
    {{> metadata/service_metadata }}

{{#service:interactions}}
def gen_metadata_service_{{service:parent_service_name}}_{{service:name}}() -> _fbthrift_metadata.ThriftMetadata:
    return _fbthrift_gen_metadata_service_{{service:parent_service_name}}_{{service:name}}(_fbthrift_metadata.ThriftMetadata(structs={}, enums={}, exceptions={}, services={}))

def _fbthrift_gen_metadata_service_{{service:parent_service_name}}_{{service:name}}({{!
}}metadata_struct: _fbthrift_metadata.ThriftMetadata) -> _fbthrift_metadata.ThriftMetadata:
    {{> metadata/service_metadata }}

{{/service:interactions}}

def _fbthrift_metadata_service_response_{{service:name}}() -> _fbthrift_metadata.ThriftServiceMetadataResponse:
    metadata = gen_metadata_service_{{service:name}}()
    context = _fbthrift_metadata.ThriftServiceContext(service_info=metadata.services["{{program:name}}.{{service:name}}"], module=_fbthrift_metadata.ThriftModuleContext(name="{{program:name}}"))
    services = [_fbthrift_metadata.ThriftServiceContextRef(module=_fbthrift_metadata.ThriftModuleContext(name=name.split('.')[0]), service_name=name) for name in metadata.services]
    return _fbthrift_metadata.ThriftServiceMetadataResponse(metadata=metadata,context=context,services=services)


{{/program:services}}

def getThriftModuleMetadata() -> _fbthrift_metadata.ThriftMetadata:
    meta = _fbthrift_metadata.ThriftMetadata(structs={}, enums={}, exceptions={}, services={})
    {{#program:enums}}
    meta = _fbthrift_current_module_enums._fbthrift_gen_metadata_enum_{{enum:name}}(meta)
    {{/program:enums}}
    {{#program:structs}}
    {{#struct:exception?}}
    meta = _fbthrift_gen_metadata_exception_{{> structs/unadapted_name}}(meta)
    {{/struct:exception?}}
    {{^struct:exception?}}
    meta = _fbthrift_gen_metadata_struct_{{> structs/unadapted_name}}(meta)
    {{/struct:exception?}}
    {{/program:structs}}
    {{#program:services}}
    meta = _fbthrift_gen_metadata_service_{{service:name}}(meta)
    {{/program:services}}
    return meta
